/*
 * @Author: Wangjun
 * @Date: 2022-11-11 10:58:40
 * @LastEditTime: 2022-11-14 16:18:44
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \golib\memory\memory.go
 * hnxr
 */
package memory

import (
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
)

type Memory struct {
	lastTime int64
	stat     runtime.MemStats
}

/**
 * @description: 获取使用内存的大小,如果是linux则查询自己的rss内存数据
 * @param {int64} now
 * @return {*}
 */
func (m *Memory) GetMemoryStats(now int64, pid int) *runtime.MemStats {
	if now == m.lastTime {
		return &m.stat
	}
	m.lastTime = now
	runtime.ReadMemStats(&m.stat)
	alloc := GetMemoryUsed(pid)
	if alloc > 0 {
		m.stat.Alloc = uint64(alloc)
	}
	return &m.stat
}

func GetMemoryUsed(pid int) int64 {
	if runtime.GOOS == "linux" && pid > 0 {
		path := fmt.Sprintf("/proc/%d/status", pid)
		data, err := os.ReadFile(path)
		if err == nil {
			lines := strings.Split(string(data), "\n")
			for _, line := range lines {
				ss := strings.Fields(line)
				if len(ss) > 1 {
					for i := range ss {
						ss[i] = strings.ToUpper(ss[i])
					}
					if strings.Contains(ss[0], "VMRSS") {
						//log.Println(line)
						alloc, err := strconv.Atoi(ss[1])
						if err == nil {
							if len(ss) > 2 {
								switch ss[2] {
								case "KB":
									alloc *= 1024
								case "MB":
									alloc *= 1024 * 1024
								case "GB":
									alloc *= 1024 * 1024 * 1024
								}
							}
							return int64(alloc)
						}
					}
				}
			}
		}
	}
	return 0
}
